// #ifndef __tenacitas_tuple_unpacker__unpack_method__h__
// #define __tenacitas_tuple_unpacker__unpack_method__h__



// /** @file */


// /** @todo */

// // ==> C++ Headers
// #include <cstddef>
// #include <tuple>
// #include <functional>
// #include <utility>
// #include <type_traits>

// // ==> 3rds Headers

// // ==> Our Headers
// #include "unpack.h"

// // ==> Namespaces
// using namespace std;

// // ==> Macro Constants

// // ==> Macro Commands


// /** ==> namespace of the organization */
// namespace tenacitas {
//     /** ==> namespace for the project */
//     namespace tuple_unpacker {

//         // ==> Typedefs 

//         // ==> Pre-Declarations

//         // ==> Attributes 

//         // ==> Functions
        
//         // ==> Classes

//         template <typename>
//         struct deduce_class;
            

//         template <typename t_return, typename t_class>
//         struct deduce_class<t_return t_class::*> {
//             typedef t_class class_type;
//             typedef t_return return_type;
//         };

//         /** 
//             @nosubgrouping 
//         */
//         template<typename t_result, typename ... t_args>
//         class unpack_method {

//             // ==> unpack_method - Friends

//         public:

//             // ==> unpack_method - Public Internal Types
            
//             typedef typename std::tuple<t_args...> tuple_type;
//             typedef t_result result_type;
//             typedef typename std::function<result_type(t_args...)>function_type; 
            
//             // ==> unpack_method - Public Constructors

//             /** Destructor */
//             ~unpack_method( ) {}
            

//             // ==> unpack_method - Public Accessors

//             // ==> unpack_method - Public Helpers

//             // ==> unpack_method - Public Processors

//             /**
//              */
//             template<typename t_class_method>
//             result_type operator()(tuple_type && p_tuple,
//                                    t_class_method p_method,
//                                    typename
//                                    deduce_class<t_class_method>::class_type &
//                                    p_obj ) {  



//                 typedef bind_method<std::tuple_size<tuple_type>::value,
//                                     t_class_method> bind_method_type;
            

//                 bind_method_type l_bind_method;
                
//                 function_type l_function = l_bind_method( p_method, p_obj );


//                 return unpack( std::move( p_tuple ), std::move( l_function ) );
//             }


//             // ==> unpack_method - Public Operators

//             // ==> unpack_method - Public Attributes

//         private:

//             // ==> unpack_method - Private Internal Types


//             /** */
//             template <size_t size, typename t_tuple_, typename t_function_>
//             class tu;

//             /** */
//             template <typename t_tuple_, typename t_function_>
//             class tu<1, t_tuple_, t_function_> {
//             public:
//                 typedef t_function_ function_type;
//                 typedef t_tuple_ tuple_type;
//                 typedef typename function_type::result_type result_type;

//                 result_type operator()(tuple_type && p_tuple,
//                                        function_type && p_function) {

//                     typedef tuple_field_traits<0, tuple_type> first_field; 

//                     std::cout << "tu<1>" << std::endl;
                    
//                     typename first_field::type l_first (
//                         std::move(std::get<0>(p_tuple)) );


//                     call_f<function_type, first_field::is_rvalue> l_call;
//                     return l_call(std::move(p_function), std::move(l_first));
                    
//                 }
//             }; 

//             /** */
//             template <typename t_tuple_, typename t_function_>
//             class tu<0, t_tuple_, t_function_> {
//             public:
//                 typedef t_function_ function_type;
//                 typedef t_tuple_ tuple_type;
//                 typedef typename function_type::result_type result_type;

//                 result_type operator()(tuple_type && p_tuple,
//                                        function_type && p_function) {
//                     return p_function();
//                 }
//             }; 


//             /** */
//             template <size_t index, typename t_tuple__>
//             struct tuple_field_traits {
//                 typedef t_tuple__ tuple_type;

//                 typedef typename std::tuple_element<index, tuple_type>::type t1;

//                 typedef typename std::remove_reference<t1>::type t2;    
    
//                 typedef typename std::remove_cv<t2>::type type;

//                 static const bool is_rvalue = std::is_rvalue_reference<t1>::value;
//             };



//             template <typename t_function__, bool is_rvalue>
//             class call_f;

//             template <typename t_function__>
//             class call_f<t_function__,true> {
//                 typedef t_function__ function_type;
//                 typedef typename function_type::result_type result_type;

//             public:
//                 template <typename t_type>
//                 result_type operator()(function_type && p_function,
//                                        t_type && p_value) {

//                     std::cout << "call_f with move" << std::endl;
//                     return p_function(std::move(p_value));
//                 }
//             };

//             template <typename t_function__>
//             class call_f<t_function__,false> {
//                 typedef t_function__ function_type;
//                 typedef typename function_type::result_type result_type;

//             public:
//                 template <typename t_type>
//                 result_type operator()(function_type && p_function,
//                                        t_type && p_value) {

//                     std::cout << "call_f wo move" << std::endl;                    
//                     return p_function(p_value);
//                 }

//             };

//             /** */
//             template <size_t num_args, typename t_class_method>
//             struct bind_method;

//             template <typename t_class_method>
//             struct bind_method<1,t_class_method> {
//                 function_type operator( )( t_class_method p_method,
//                                            typename
//                                            deduce_class<t_class_method>::class_type &
//                                            p_obj ) {

//                     return std::bind( p_method, std::ref( p_obj ),
//                                       std::placeholders::_1 );
//                 }
//             };
            


//             // ==> unpack_method - Private Constructors

//             // ==> unpack_method - Private Accessors

//             // ==> unpack_method - Private Helpers

//             // ==> unpack_method - Private Processors

//             /** */
//             result_type unpack(tuple_type && p_tuple,
//                                function_type && p_function) {

//                 tu<tuple_size<tuple_type>::value, tuple_type, function_type> l_tu;
//                 return l_tu(std::move(p_tuple), std::move(p_function));
//             }


//             // ==> unpack_method - Private Operators

//             // ==> unpack_method - Private Attributes
//         };
//     }
// }

// // =============================================================================
// // I M P L E M E N T A T I O N
// // =============================================================================

// using namespace tenacitas::tuple_unpacker;


// #endif
